package com.douya.common.listener;

import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.ZoneAwareLoadBalancer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory;
import org.springframework.cloud.openfeign.ribbon.FeignLoadBalancer;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.List;

/**
 * nacos服务状态监听
 *
 * @Author hcy
 * @Date 2024/3/28  14:59
 */
@Slf4j
@Component
@ConditionalOnProperty(value = "spring.cloud.nacos.subscribed", havingValue = "true")
public class NacosServerStatusListener {

    @Resource
    private CachingSpringLoadBalancerFactory cachingSpringLoadBalancerFactory;

    @Resource
    private NacosDiscoveryProperties nacosDiscoveryProperties;

    @Value("${spring.cloud.nacos.subscribed-services}")
    private List<String> serviceList;

    @PostConstruct
    public void init() {
        try {
            NamingService namingService = nacosDiscoveryProperties.namingServiceInstance();
            serviceList.forEach(service -> {
                try {
                    namingService.subscribe(service, (event -> {
                        try {
                            FeignLoadBalancer feignLoadBalancer = cachingSpringLoadBalancerFactory.create(service);
                            if (feignLoadBalancer != null) {
                                ILoadBalancer iLoadBalancer = feignLoadBalancer.getLoadBalancer();
                                if (iLoadBalancer != null) {
                                    ZoneAwareLoadBalancer loadBalancer = (ZoneAwareLoadBalancer) iLoadBalancer;
                                    loadBalancer.updateListOfServers();
                                    log.info("Refreshed Ribbon server instances successfully for service: {}", service);
                                }
                            }
                        } catch (Exception e) {
                            log.error("Failed to refresh Ribbon server instances for service: {}", service, e);
                        }
                    }));
                } catch (NacosException e) {
                    log.error("Failed to subscribe to Nacos service: {}", service, e);
                }
            });
        } catch (Exception e) {
            log.error("Failed to get Nacos service information", e);
        }
    }
}
